package com.piece.module.flowable.service;

import com.piece.core.framework.exception.ServerException;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.collection.CollectionUtil;
import com.piece.core.framework.util.object.ObjectUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.jpa.repository.BaseService;
import com.piece.module.flowable.constants.ExceptionConstants;
import com.piece.module.flowable.model.WfDeployForm;
import com.piece.module.flowable.model.WfForm;
import com.piece.module.flowable.repository.WfDeployFormRepository;
import com.piece.module.flowable.repository.WfFormRepository;
import com.piece.module.flowable.util.FlowUtil;
import com.piece.module.flowable.util.UserTaskUtil;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Service
@Transactional
public class WfDeployFormService extends BaseService<WfDeployForm, String> {

    @Autowired
    private WfDeployFormRepository wfDeployFormRepository;

    @Autowired
    private WfFormRepository wfFormRepository;

    @PostConstruct
    public void initRepository() {
        setRepository(wfDeployFormRepository);
    }

    @Override
    public WfDeployForm insert(WfDeployForm deployForm) throws Exception {
        // 删除部署流程和表单的关联关系
        wfDeployFormRepository.deleteByProperties("deployId", deployForm.getDeployId());
        // 新增部署流程和表单关系
        return super.insert(deployForm);
    }

    /**
     * 部署流程和表单关联信息
     */
    public List<WfDeployForm> saveInternal(String deployId, BpmnModel bpmnModel) throws Exception {
        List<WfDeployForm> deployFormList = new ArrayList<>();
        // 获取开始节点
        StartEvent startEvent = FlowUtil.getStartEvent(bpmnModel);
        if (ObjectUtil.isNull(startEvent)) {
            throw new ServerException(ExceptionConstants.NOT_EXIST, "开始节点");
        }
        // 保存开始节点表单信息
        WfDeployForm startDeployForm = buildDeployForm(deployId, startEvent);
        if (ObjectUtil.isNotNull(startDeployForm)) {
            deployFormList.add(startDeployForm);
        }
        // 保存用户节点表单信息
        Collection<UserTask> userTasks = UserTaskUtil.getAllUserTaskEvent(bpmnModel);
        if (CollectionUtil.isNotEmpty(userTasks)) {
            for (UserTask userTask : userTasks) {
                WfDeployForm userTaskDeployForm = buildDeployForm(deployId, userTask);
                if (ObjectUtil.isNotNull(userTaskDeployForm)) {
                    deployFormList.add(userTaskDeployForm);
                }
            }
        }
        return batchInsert(deployFormList);
    }

    /**
     * 构建部署表单关联信息对象
     */
    private WfDeployForm buildDeployForm(String deployId, FlowNode node) {
        String formKey = null;
        if (node instanceof StartEvent) {
            formKey = ((StartEvent) node).getFormKey();
        } else if (node instanceof UserTask) {
            formKey = ((UserTask) node).getFormKey();
        }
        if (StringUtil.isEmpty(formKey)) {
            return null;
        }

        Long formId = Convert.toLong(StringUtil.substringAfter(formKey, "key_"));
        WfForm wfForm = wfFormRepository.findById(formId);
        if (ObjectUtil.isNull(wfForm)) {
            throw new ServerException(ExceptionConstants.MODEL_DEPLOY_FAIL_FORM_NOT_CONFIG, null);
        }

        WfDeployForm deployForm = new WfDeployForm();
        deployForm.setDeployId(deployId);
        deployForm.setNodeKey(node.getId());
        deployForm.setNodeName(node.getName());
        deployForm.setFormName(wfForm.getFormName());
        deployForm.setFormKey(formKey);
        deployForm.setFormId(wfForm.getFormId());
        deployForm.setContent(wfForm.getContent());
        return deployForm;
    }
}
